package com.chenl.consumer.util;//package com.chenl.provider.controller;
//
//import com.alibaba.fastjson.JSONObject;
//import lombok.extern.slf4j.Slf4j;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.script.DefaultRedisScript;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//import javax.servlet.http.HttpServletRequest;
//import java.lang.reflect.Method;
//import java.util.ArrayList;
//import java.util.List;
//
///**
//*redis+lua 计数器实现限流
///*/
//@Slf4j
//@Aspect
//@Configuration
//public class LimitAspect {
//    @Autowired
//    private RedisTemplate redisTemplate;
//
//
//    private static final DefaultRedisScript<Long> RATE_LIMIT;
//    //传入限流key KEYS[1],限流个数 ARGV[1],过期时间(秒) ARGV[2]
//    static {
//        StringBuilder lua = new StringBuilder();
//        lua.append("local c");
//        lua.append("\nc = redis.call('get',KEYS[1])");
//        lua.append("\nif c and tonumber(c) > tonumber(ARGV[1]) then");//实际调用次数超过阈值，则直接返回
//        lua.append("\nreturn tonumber(c)");
//        lua.append("\nend");
//        lua.append("\nc = redis.call('incr',KEYS[1])");// 执行计算器自加
//        lua.append("\nif tonumber(c) == 1 then");// 执行计算器自加
//        lua.append("\nredis.call('expire',KEYS[1],ARGV[2])");//从第一次调用开始限流，设置对应键值的过期
//        lua.append("\nend");
//        lua.append("\nreturn tonumber(c)");
//        RATE_LIMIT = new DefaultRedisScript<>(lua.toString(), Long.class);
//    }
//
//    @Around("@annotation(cn.modo.dmpmanage.controller.temp.RateLimit)")
//    public Object interceptor(ProceedingJoinPoint joinPoint) throws Throwable {
//
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        Method method = signature.getMethod();
//        Class<?> targetClass = method.getDeclaringClass();
//        RateLimit rateLimit = method.getAnnotation(RateLimit.class);
//
//        if (rateLimit != null) {
//            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//            String ipAddress = getIpAddr(request);
//
//            StringBuffer stringBuffer = new StringBuffer();
//            if (rateLimit.type().equals(AnnotationType.RATE_LIMIT_IP)){//根据ip限流
//                stringBuffer.append(ipAddress).append("_")
//                        .append(targetClass.getName()).append("_")
//                        .append(method.getName()).append("_")
//                        .append(rateLimit.key());
//            }else if (rateLimit.type().equals(AnnotationType.RATE_LIMIT_INTERFACE)){//根据接口限流
//                         stringBuffer
//                        .append(targetClass.getName()).append("_")
//                        .append(method.getName()).append("_")
//                        .append(rateLimit.key());
//            }
//
//
//            List<String> keys = new ArrayList<>();
//            keys.add(stringBuffer.toString().replace(".","").replace(" ",""));
//            log.info("LimitAspect---KEYS:{},ARGV[1]:{},ARGV[2]:{}", JSONObject.toJSONString(keys),rateLimit.count(),rateLimit.time());
//            Long execute = (Long) redisTemplate.execute(RATE_LIMIT, keys, rateLimit.count(), rateLimit.time());
//            log.info("LimitAspect---count:{}", execute);
//            if (execute != null && execute.intValue() != 0 && execute.intValue() <= rateLimit.count()) {
//                log.info("LimitAspect---限流时间段内正常访问第：{} 次,key:{}", execute.toString(), stringBuffer);
//                return joinPoint.proceed();
//            }else {
//                log.info("LimitAspect---当前已经到最大限流次数：{} 次,key:{}", rateLimit.count(), stringBuffer);
//                throw  new RuntimeException("接口限流啦~");
//            }
//
//        } else {
//            return joinPoint.proceed();
//        }
//    }
//
//     public static String getIpAddr(HttpServletRequest request) {
//        String ip = null;
//
//        //X-Forwarded-For：Squid 服务代理
//        String ipAddresses = request.getHeader("X-Forwarded-For");
//
//        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//            //Proxy-Client-IP：apache 服务代理
//            ipAddresses = request.getHeader("Proxy-Client-IP");
//        }
//
//        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//            //WL-Proxy-Client-IP：weblogic 服务代理
//            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
//        }
//
//        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//            //HTTP_CLIENT_IP：有些代理服务器
//            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
//        }
//
//        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//            //X-Real-IP：nginx服务代理
//            ipAddresses = request.getHeader("X-Real-IP");
//        }
//
//        //有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
//        if (ipAddresses != null && ipAddresses.length() != 0) {
//            ip = ipAddresses.split(",")[0];
//        }
//
//        //还是不能获取到，最后再通过request.getRemoteAddr();获取
//        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
//            ip = request.getRemoteAddr();
//        }
//        return ip;
//    }
//
//}